﻿//-----------------------------------------------------------------------
// <copyright file="ObjectX.cs" company="Bugger Sisters Inc.">
//     Copyright (c) Bugger Sisters Inc. All rights reserved.
// </copyright>
// <author>Sergey Tyshkovets</author>
//-----------------------------------------------------------------------

namespace MagicTheGathering.Framework.Extensions
{
    using FieldInfo = System.Reflection.FieldInfo;
    using Object = System.Object;
    using PropertyInfo = System.Reflection.PropertyInfo;

    public static class ObjectX
    {
        public static object GetValue(this object obj, string property)
        {
            var propertyInfo = obj.GetType().GetProperty(property);
            if (propertyInfo != null)
            {
                return propertyInfo.GetValue(obj, null);
            }
            var properties = StringX.Split(property, ".");
            if (properties.Length > 1)
            {
                PropertyInfo tempPropertyInfo;
                Object tempObj = obj;

                foreach (var propertyName in properties)
                {
                    if (tempObj != null)
                    {
                        tempPropertyInfo = tempObj.GetType().GetProperty(propertyName);
                        if (tempPropertyInfo != null)
                        {
                            tempObj = tempPropertyInfo.GetValue(tempObj, null);
                        }
                        else
                        {
                            return tempObj;
                        }
                    }
                }
                return tempObj;
            }
            return null;
        }

        public static void SetValue(this object obj, string property, object value)
        {
            var fieldInfo = obj.GetType().GetField(property);
            if (fieldInfo != null)
            {
                fieldInfo.SetValue(fieldInfo, value);
                return;
            }

            var fields = property.Split('.');
            if (fields.Length > 1)
            {
                FieldInfo tempFieldInfo = null;
                Object tempObj = obj;
                int propertyIndex = 0;

                foreach (var propertyName in fields)
                {
                    if (tempObj != null)
                    {
                        tempFieldInfo = tempObj.GetType().GetField(propertyName);
                        if (tempFieldInfo != null && propertyIndex != fields.Length - 1)
                        {
                            tempObj = tempFieldInfo.GetValue(tempObj);
                        }
                        else
                        {
                            break;
                        }
                    }

                    propertyIndex++;
                }

                if (tempFieldInfo != null)
                {
                    tempFieldInfo.SetValue(tempObj, value);
                }
            }
        }

        public static void SetFieldOrProperty(this object obj, string property, object value)
        {
            var fieldInfo = obj.GetType().GetField(property);
            if (fieldInfo != null)
            {
                fieldInfo.SetValue(fieldInfo, value);
                return;
            }

            var propertyInfo = obj.GetType().GetProperty(property);

            if (propertyInfo != null && value != null)
            {
                if (propertyInfo.PropertyType == typeof(bool))
                {
                    bool valueToSet;
                    if (bool.TryParse(value.ToString(), out valueToSet))
                    {
                        propertyInfo.SetValue(obj, valueToSet, null);
                        return;
                    }
                }

                if (propertyInfo.PropertyType == typeof(int))
                {
                    int valueToSet;
                    if (int.TryParse(value.ToString(), out valueToSet))
                    {
                        propertyInfo.SetValue(obj, valueToSet, null);
                        return;
                    }
                }

                if (propertyInfo.PropertyType == typeof(double))
                {
                    double valueToSet;
                    if (double.TryParse(value.ToString(), out valueToSet))
                    {
                        propertyInfo.SetValue(obj, valueToSet, null);
                        return;
                    }
                }

                if (propertyInfo.PropertyType == typeof(string))
                {
                    propertyInfo.SetValue(obj, value.ToString(), null);
                    return;
                }
            }
        }
    }
}
